package cn.com.victorysoft.ylgl.service.commons.mybatis.paging;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.com.victorysoft.ylgl.service.commons.mybatis.paging.dialect.AbstractDialect;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/***
 * @author gechaoqing
 */
public class CountHelper {
    private static final Logger logger = LoggerFactory.getLogger(CountHelper.class);
    private static final String ORDER_BY_REGEX = "order\\s*by[\\w|\\W|\\s|\\S]*";
    private static final String OVER_ORDER_BY_REGEX = "over\\s*\\([\\w|\\W|\\s|\\S]*order\\s*by[\\w|\\W|\\s|\\S]*\\)";
    private static final String ORDER_BY_KEYWORD = "order\\s+by";

    public static int getCount(MappedStatement ms, Connection connection, Object parameterObject, AbstractDialect dialect)
            throws SQLException {
        BoundSql boundSql = ms.getBoundSql(parameterObject);

        String sql = boundSql.getSql().trim();

        String countSql = dialect.getCountString(sql);

        logger.debug("Total count SQL [{}]", countSql);
        logger.debug("Parameters: {} ", parameterObject);

        PreparedStatement stmt = null;
        try {
            stmt = connection.prepareStatement(countSql);

            DefaultParameterHandler handler = new DefaultParameterHandler(ms, parameterObject, boundSql);
            handler.setParameters(stmt);
            ResultSet rs = stmt.executeQuery();

            int count = 0;
            if (rs.next()) {
                count = rs.getInt(1);
            }
            return count;
        } finally {
            closeStatement(stmt);
        }
    }

    public static boolean containOrder(String sql) {
        return containRegex(sql, "order\\s+by");
    }

    public static boolean containOver(String sql) {
        return containRegex(sql, "over\\s*\\([\\w|\\W|\\s|\\S]*order\\s*by[\\w|\\W|\\s|\\S]*\\)");
    }

    public static boolean containRegex(String sql, String regex) {
        Pattern pattern = Pattern.compile(regex, 2);
        Matcher matcher = pattern.matcher(sql);
        return matcher.find();
    }

    private static final Pattern PATTERN = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", 2);

    public static String removeOrders(String sql) {
        Matcher m = PATTERN.matcher(sql);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "");
        }
        m.appendTail(sb);
        return sb.toString();
    }

    private static void closeStatement(Statement statement) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
            }
        }
    }
}
